﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using blackhouse.JavaScript.JQuery;
using blackhouse.WebNemo.Business;
using blackhouse.WebNemo.Business.Groups;
using System.Web.UI.HtmlControls;
using System.Globalization;
using blackhouse.WebNemo.Business.Translate;
using blackhouse.WebNemo.Business.Extensionable;

namespace blackhouse.WebNemo.Web.Controls {
    public partial class RecordEdit : System.Web.UI.UserControl {

        #region Fields

        private int groupId;
        private int recordId;
        private Factory factory = Factory.Instance();
        private GroupRecord record;
        private IGroup group;
        private GroupExtension groupExtension;
        private SplitColumns splitColumns;
        private List<EditController> controllers = new List<EditController>();
        private bool autoClose;
        private string returnUrl;
        private CultureInfo editTranslate = CultureInfo.InvariantCulture;
        private ITranslate supportTranslate;

        #endregion

        #region Event Handlers

        protected override void OnInit(EventArgs e) {
            base.OnInit(e);

            this.ReadParameters();
        }

        protected override void OnLoad(EventArgs e) {
            base.OnLoad(e);

            this.SetInstance();
            this.PopulateControls();

            NemoJsLibrary js = new NemoJsLibrary();
            js.IncludeJQueryPrettyFileInput();
            js.IncludeFile("nemo.editrecord");
        }

        #endregion

        #region Methods

        private void ReadParameters() {
            string sGroupId = Request.QueryString["groupId"];
            string sRecordId = Request.QueryString["recordId"];

            Int32.TryParse(sGroupId, out this.groupId);
            Int32.TryParse(sRecordId, out this.recordId);

            this.autoClose = Request.QueryString["autoClose"] == "1" || Request.QueryString["autoClose"] == "true";
            this.returnUrl = Request.QueryString["returnUrl"];
            if (String.IsNullOrEmpty(this.returnUrl)) {
                if (IsPostBack)
                    this.returnUrl = Request.Form[this.hfReturnUrl.UniqueID];
                else if (Request.UrlReferrer != null)
                    this.returnUrl = Request.UrlReferrer.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
            }
            string translate = Request.QueryString["translate"];
            if (!String.IsNullOrEmpty(translate)) {
                try { this.editTranslate = CultureInfo.GetCultureInfo(translate); }
                catch { this.editTranslate = CultureInfo.InvariantCulture; }
            }
        }

        private void SetInstance() {
            if (this.groupId > 0) {
                this.record = new GroupRecord(this.groupId, this.recordId);
                this.group = this.record.GetGroup();
                this.splitColumns = Factory.Instance().GetSplitColumns(this.group);
                this.groupExtension = new Extensions(this.group).GetGroupExtension();
                if (this.editTranslate != CultureInfo.InvariantCulture) {
                    this.splitColumns.Filter = (gc => gc.ColumnType == FieldType.ValueField && gc.DataType == typeof(string));
                    this.supportTranslate = this.factory.GetTranslates();
                }
            }
        }

        private void PopulateControls() {
            this.hfReturnUrl.Value = this.returnUrl;
            if (this.record.RecordId == this.recordId && this.record.BelongsToGroupId == this.groupId) {
                if (this.record.RecordId > 0)
                    this.ltlIdx.Text = this.record.RecordId.ToString();
                else
                    this.ltlIdx.Text = " - ";
                if (!IsPostBack) {
                    if (this.record.RecordId > 0) {
                        RecordIdentyficator ident = new RecordIdentyficator();
                        string i = ident.GetDisplayIdentyficator(record);
                        this.lnkIdentyficator.Text = i;
                        this.lnkIdentyficator.ToolTip = i;
                    }

                }
                if (this.record.RecordId > 0) {
                    this.ltlCreated.Text = string.Format("{0} ({1:F})", WebNemoUtils.GetDisplayUser(this.record.CreatedBy), this.record.CreatedTime);
                    this.ltlModified.Text = string.Format("{0} ({1:F})", WebNemoUtils.GetDisplayUser(this.record.LastModifiedBy), this.record.LastModifiedTime);
                }
                else {
                    this.ltlCreated.Text = " - ";
                    this.ltlModified.Text = " - ";
                }
                if (!string.IsNullOrEmpty(this.returnUrl))
                    this.lnkCancel.NavigateUrl = this.returnUrl;
                else {
                    NemoUrl url = NemoUrl.Get();
                    url.View = NemoUrlView.RecordList;
                    url.GroupId = this.groupId;
                    url.RecordId = 0;
                    this.lnkCancel.NavigateUrl = url.GetUrl();
                }
                if (autoClose)
                    this.lnkCancel.Attributes.Add("data-type", "close-popup");

                IEnumerable<int> tabsIdx;
                if (this.splitColumns.DividedIntoTabs) {
                    if (this.splitColumns.HaveNotAssignedColumns)
                        tabsIdx = Enumerable.Range(-1, this.splitColumns.TabCounts + 1);
                    else
                        tabsIdx = Enumerable.Range(0, this.splitColumns.TabCounts);
                }
                else
                    tabsIdx = new int[] { -1 }.ToList();

                this.rptTabs.DataSource = tabsIdx;
                this.rptTabs.DataBind();

                if (this.splitColumns.DividedIntoTabs) {
                    bool selected = false;
                    foreach (int tabIdx in tabsIdx) {
                        string name = (tabIdx == -1) ? "Ogólne" : this.splitColumns.GetTabName(tabIdx);
                        this.nemoTabMenu.AddTabMenuItem(tabIdx, name, selected);
                        selected = false;
                    }
                    this.pnlTabMargin.Visible = true;

                }

            }
        }

        private bool activeTabSelected;

        protected void rptTabMenu_ItemDataBound(object sender, RepeaterItemEventArgs e) {
            switch (e.Item.ItemType) {
                case ListItemType.AlternatingItem:
                case ListItemType.Item:
                    int tabIdx = (int)e.Item.DataItem;
                    HtmlGenericControl liItem = e.Item.FindControl("liItem") as HtmlGenericControl;
                    Literal ltlTabName = e.Item.FindControl("ltlTabName") as Literal;

                    if (liItem != null)
                        liItem.Attributes.Add("tab-id", tabIdx.ToString());

                    if (ltlTabName != null) {
                        if (tabIdx == -1)
                            ltlTabName.Text = "Ogólne";
                        else
                            ltlTabName.Text = this.splitColumns.GetTabName(tabIdx);
                    }
                    break;
            }
        }

        protected void rptTabs_ItemDataBound(object sender, RepeaterItemEventArgs e) {
            switch (e.Item.ItemType) {
                case ListItemType.AlternatingItem:
                case ListItemType.Item:
                    Panel pnlRecordDisplay = e.Item.FindControl("pnlRecordDisplay") as Panel;
                    Repeater rptData = e.Item.FindControl("rptData") as Repeater;
                    int tabIdx = (int)e.Item.DataItem;

                    if (pnlRecordDisplay != null && rptTabs != null) {
                        if (this.splitColumns.DividedIntoTabs) {// grupa jest podzielona na taby
                            if (activeTabSelected)
                                pnlRecordDisplay.CssClass = pnlRecordDisplay.CssClass + " hidden-tab-record-display";
                            else
                                activeTabSelected = true;
                            pnlRecordDisplay.Attributes.Add("tab-id", tabIdx.ToString());
                            if (tabIdx >= 0)
                                rptData.DataSource = this.GetEditColumnsDataSource(this.splitColumns.GetEditColumns(tabIdx));
                            else
                                rptData.DataSource = this.GetEditColumnsDataSource(this.splitColumns.GetNotAssignedEditColumns());
                        }
                        else {
                            IEnumerable<GroupColumn> columns = this.record.GetGroup().Columns.Where(gc => this.groupExtension.ShouldUseThisColumnInEditor(gc));
                            if (this.splitColumns.Filter != null)
                                columns = columns.Where(this.splitColumns.Filter);
                            columns = columns.OrderBy(gc => gc.ColumnSort).ThenBy(gc => gc.ColumnName);
                            rptData.DataSource = this.GetEditColumnsDataSource(columns);
                        }

                        rptData.DataBind();
                    }
                    break;

            }
        }

        private IEnumerable<EditController> GetEditColumnsDataSource(IEnumerable<GroupColumn> columns) {
            //VirtualColumns virtualize = new VirtualColumns(this.record.BelongsToGroupId);
            List<EditController> controllers = new List<EditController>();
            foreach (GroupColumn column in columns) {
                EditController controller = null;
                //if (virtualize.IsVirtualizationColumn(column)) {
                //    VirtualColumn virtualColumn = virtualize.GetVirtualColumn(column);
                //    controller = this.controllers.FirstOrDefault(ec => ec.VirtualColumn == virtualColumn);
                //    if (controller == null) {
                //        controller = new EditController(virtualColumn, record);
                //        controllers.Add(controller);
                //    }
                //    controller.AddColumn(column);
                //}
                //else {
                controller = new EditController(column, record);
                controllers.Add(controller);
                //}
            }
            return controllers;
        }

        protected void rptData_ItemDataBound(object sender, RepeaterItemEventArgs e) {
            switch (e.Item.ItemType) {
                case ListItemType.AlternatingItem:
                case ListItemType.Item:

                    // GroupColumn column = e.Item.DataItem as GroupColumn;
                    Label lblName = e.Item.FindControl("lblName") as Label;
                    Label lblDescription = e.Item.FindControl("lblDescription") as Label;
                    Panel pnlEdit = e.Item.FindControl("pnlEdit") as Panel;
                    Panel pnlValidators = e.Item.FindControl("pnlValidators") as Panel;
                    Panel pnlHolder = e.Item.FindControl("pnlHolder") as Panel;
                    HyperLink lnkAddTranslate = e.Item.FindControl("lnkAddTranslate") as HyperLink;
                    Control ctrlRequired = e.Item.FindControl("ctrlRequired");
                    Panel pnlOryginalTranslate = e.Item.FindControl("pnlOryginalTranslate") as Panel;
                    ITextControl lblOryginalText = e.Item.FindControl("lblOryginalText") as ITextControl;

                    if (this.editTranslate != CultureInfo.InvariantCulture) // jeżeli edytujemy tłumaczenia to nieużywamy linku do tłumaczenia, wystarczy go tylko ukryć
                        lnkAddTranslate = null;

                    EditController controller = e.Item.DataItem as EditController;

                    if (controller != null) {
                        controller.Populate(lblName,
                                                                        ctrlRequired,
                                                                        lblDescription,
                                                                        pnlEdit,
                                                                        pnlValidators,
                                                                        pnlHolder,
                                                                        lnkAddTranslate,
                                                                        e.Item);
                    }

                    if (controller.IsPopulated) {
                        this.controllers.Add(controller);
                        if (this.editTranslate != CultureInfo.InvariantCulture) {
                            ITranslate currentTransate = this.supportTranslate.GetTranslate(this.groupId, controller.Column.ColumnId, this.recordId);
                            string tVal = currentTransate.Translation(this.editTranslate);
                            if (String.IsNullOrEmpty(tVal))
                                tVal = currentTransate.TranslationOryginal();
                            controller.ReSetValue(currentTransate.Translation(this.editTranslate));
                            if (pnlOryginalTranslate != null && lblOryginalText != null) {
                                pnlOryginalTranslate.Visible = true;
                                lblOryginalText.Text = currentTransate.TranslationOryginal();
                            }
                        }
                        if (lnkAddTranslate != null)
                            lnkAddTranslate.Attributes.Add("data-type", "open-popup");
                    }

                    break;
            }
        }

        protected void bntSave_Click(object sender, EventArgs e) {
            bool saveTranslates = this.editTranslate != CultureInfo.InvariantCulture;
            foreach (EditController controller in this.controllers) {
                if (saveTranslates)
                    this.supportTranslate.GetTranslate(this.groupId, controller.Column.ColumnId, this.recordId).SetTranslation(this.editTranslate, controller.GetValue());
                else
                    controller.SaveInRecord(); // odczytuje dane wprowadzone przez użytkownika do GroupRecord
            }

            if (!saveTranslates) { // tłumaczenia są zapisane wyżej tak więc niezależnie od walidacji i tak będzie już zapisane, tak więc olewka - narazie :)
                Page.Validate(); // sprawdza poprawność danych, w tym wywołuje walidację całego rekordu
                if (!Page.IsValid)
                    return;

                this.record.Save();
            }

            if (!String.IsNullOrEmpty(this.hfIdentyficator.Value))
                this.record.ChangeIdentyficator(this.hfIdentyficator.Value);
            else
                this.record.UpdateIdentyficator();

            string mode = Request.QueryString["mod"];
            if (this.autoClose) {
                this.pnlAutoCloseScript.Visible = true;
                //this.ltlScriptRecordId.Text = this.record.RecordId.ToString();
                //this.ltlScriptGroupId.Text = this.record.BelongsToGroupId.ToString();
            }
            else {
                if (mode == "popup")
                    Response.Redirect("Complete.aspx?recordId=" + this.record.RecordId + "&groupId=" + this.record.BelongsToGroupId);
                else {
                    if (!string.IsNullOrEmpty(this.returnUrl)) {
                        string url = this.returnUrl.ReplaceEx("[recordid]", this.recordId.ToString());
                        string appendUrl = "?";
                        if (this.returnUrl.Contains("?"))
                            appendUrl = "&";
                        appendUrl += "message=saveOk";
                        Response.Redirect(url + appendUrl);
                    }
                    else {
                        NemoUrl url = NemoUrl.Get();
                        url.GroupId = this.record.BelongsToGroupId;
                        url.RecordId = 0;
                        url.View = NemoUrlView.RecordList;
                        url.ShowMessage(NemoMessage.SaveOk);
                        Response.Redirect(url.GetUrl());
                    }
                }
            }
        }

        protected void cvRecordValidation_ServerValidate(object source, ServerValidateEventArgs args) {
            if (this.record.Extension != RecordExtension.NULL) {
                CustomValidator cv = source as CustomValidator;
                string msg = String.Empty;
                if (!this.record.Extension.RecordIsValid(out msg)) {
                    args.IsValid = false;
                    cv.ErrorMessage = msg;
                    cv.Text = msg;
                }
            }
        }

        #endregion

    }
}